﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Citi.BOExtraction.WindowsFormUI;
using System.IO;
using System.Configuration;
using Citi.Helpers;
using System.Timers;
using System.Threading;
using System.Net;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Citi.BOExtraction.Util;

namespace Citi.BOExtraction
{
    public partial class BoExtraction : Form
    {
        string reportName;
        string Url{get;set;}
        string userLogin;
        string pathToSave;
        bool joinSheets;
        string newSheetName;
        static string LogPath { get; set; }
        SHDocVw.WebBrowser_V1 axbrowser;
        private const string JavascriptFrameBody = "window.frames['headerPlusFrame'].frames['dataFrame'].frames['workspaceFrame'].frames['workspaceBodyFrame']";

        ///<summary>
        ///Fires before navigation occurs in the given object (on either a window or frameset element).
        ///</summary>
        ///<param name="pDisp">Object that evaluates to the top level or frame WebBrowser object corresponding to the navigation.</param>
        ///<param name="url">String expression that evaluates to the URL to which the browser is navigating.</param>
        ///<param name="Flags">Reserved. Set to zero.</param>
        ///<param name="TargetFrameName">String expression that evaluates to the name of the frame in which the resource will be displayed, or Null if no named frame is targeted for the resource.</param>
        ///<param name="PostData">Data to send to the server if the HTTP POST transaction is being used.</param>
        ///<param name="Headers">Value that specifies the additional HTTP headers to send to the server (HTTP URLs only). The headers can specify such things as the action required of the server, the type of data being passed to the server, or a status code.</param>
        ///<param name="Cancel">Boolean value that the container can set to True to cancel the navigation operation, or to False to allow it to proceed.</param>
        private delegate void BeforeNavigate2(object pDisp, ref dynamic url, ref dynamic Flags, ref dynamic TargetFrameName, ref dynamic PostData, ref dynamic Headers, ref bool Cancel);

        ///<summary>
        ///Fires to indicate that a file download is about to occur. If a file download dialog box can be displayed, this event fires prior to the appearance of the dialog box.
        ///</summary>
        ///<param name="bActiveDocument">A Boolean that specifies whether the file is an Active Document.</param>
        ///<param name="bCancel">A Boolean that specifies whether to continue the download process and display the download dialog box.</param>
        private delegate void FileDownload(bool bActiveDocument, ref bool bCancel);
 

        public BoExtraction(string reportName, string url, string userLogin, string pathToSave, bool joinSheets, string newSheetName)
        {
            InitializeComponent();

            this.reportName = reportName;
            this.Url = url;
            this.pathToSave = pathToSave;
            this.userLogin = userLogin;
            this.joinSheets = joinSheets;
            this.newSheetName = newSheetName;
        }

        private void BoExtraction_Load(object sender, EventArgs e)
        {
            //var hrUrl = ("https://hronline.brazil.citigroup.net/siteminderagent/forms/login.fcc");
            //var p2pUrl = "https://signon.p2p.citigroup.net/";
            //var i7UatUrl = "https://uat.brazilweb.br.citicorp.com/siteminderagent/forms/login.fcc?TYPE=33554433&REALMOID=06-3f395aef-bd9c-0006-0000-534600005346&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=-SM-d2MymqAkcJRTP8thRFmJWpl41jCQfYTR%2fi8pnlogZGruwMl8S1FUuyGVwJyyNylejod1uUPjavbLoz1HKPzHs2NfAVcAVjKZ&TARGET=-SM-%2fAPPSL%2fi7%2fconfiguracao%2easpx%2fsistema";
            //var gdwUrl = "https://gdw-wfr.nam.nsroot.net/wfrbo/AnalyticalReporting/WebiView.do?bypassLatestInstance=true&cafWebSesInit=true&appKind=InfoView&service=/InfoViewApp/common/appService.do&loc=en&pvl=en_US&ctx=standalone&actId=468&objIds=921989&containerId=28146&pref=maxOpageU%3D50%3BmaxOpageUt%3D200%3BmaxOpageC%3D10%3Btz%3DAmerica%2FNew_York%3BmUnit%3Dinch%3BshowFilters%3Dtrue%3BsmtpFrom%3Dtrue%3BpromptForUnsavedData%3Dtrue%3B";
            //var pearlUrl = "https://pearl.nj.ssmb.com/siteminderagent/forms/login.fcc?TYPE=33554433&REALMOID=06-fb51622c-add9-1001-9bdc-847a5366ff21&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=-SM-TSXzCZBCWQfzzR6LEV6XtEMrota02ItSl0QgFPxXin03Wt9NJusCYSasBcT6zdoJT%2fuU6B%2b%2b02sSh2OVblMd8gXfnNQ9TyP9&TARGET=-SM-%2fpsp%2fplpfprg%2fEMPLOYEE%2fEPM%2fc%2fBCC_REPORTS_HOME%2eBCC_BO_R3_LINK%2eGBL%3fFolderPath%3dPORTAL_ROOT_OBJECT%2eBCC_COUNTRY_CORE%2eBCC_REPORTING%2eBCC_BO_R3_LINK_GBL%26IsFolder%3dfalse%26IgnoreParamTempl%3dFolderPath-%2cIsFolder";

            //var url = pearlUrl;
            //url = "https://pearl.nj.ssmb.com/psp/plpfprg/EMPLOYEE/EPM/s/WEBLIB_PTPP_SC.HOMEPAGE.FieldFormula.IScript_AppHP?pt_fname=BCC_COUNTRY_CORE&FolderPath=PORTAL_ROOT_OBJECT.BCC_COUNTRY_CORE&IsFolder=true";
            //url = "https://pearl.nj.ssmb.com/psc/plpfprg/EMPLOYEE/EPM/s/WEBLIB_PTPP_SC.HOMEPAGE.FieldFormula.IScript_AppHP?scname=BCC_COUNTRY_CORE&secondary=true&fname=BCC_REPORTING&pt_fname=BCC_REPORTING&PortalCacheContent=true&PSCache-Control=role%2cmax-age%3d60&FolderPath=PORTAL_ROOT_OBJECT.BCC_COUNTRY_CORE.BCC_REPORTING&IsFolder=true";
            //url = "http://plboprg.wlb2.nam.nsroot.net:14620/bobjpsenterprise/jsp/ContextualAwareness/initURE.jsp?infoview=http://plboprg.wlb2.nam.nsroot.net:14620/PartnerPlatformService/service/app/logon.object&vendor=PeopleSoft&cms=corpbo126p.nam.nsroot.net:14670&auth=secpsenterprise&domain=PLPFPRG&token=AAAAqAECAwQAAQAAAAACvAAAAAAAAAAsAARTaGRyAgBOdQgAOAAuADEAMBRI5t1/PBZ6D7YofAnzOlcW4F2AdwAAAGgABVNkYXRhXHicHYtLDkBAEAVrEEsr1yCGFqx9ZiMycQGncDuH8+ikqpN+r4HbJWmGQ5M8nwt2FgxPJ6aclYNQMhO4iEojmzgJRkujklFpd7IefvfUwmTPKA/KTZev9QK0pQwb";
            //browser.LogSingleSignOn("ND61955", SecurityHelper.LoginType.Sso, "https://procure2pay.citigroup.net/");

            LogPath = string.Format(ConfigurationManager.AppSettings["LogPath"], FileHelper.MakeValidFileName(reportName));
            if (File.Exists(LogPath)) File.Delete(LogPath);

            axbrowser = (SHDocVw.WebBrowser_V1)browser.ActiveXInstance;
            axbrowser.NewWindow += new SHDocVw.DWebBrowserEvents_NewWindowEventHandler(Web_V1_NewWindow);
            browser.Navigated += browser_Navigated;


            string uri = string.Empty;
            browser.LogSingleSignOn(userLogin, SecurityHelper.LoginType.Sso, Url);
        }

        

        void browser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            if (!e.Url.OriginalString.Contains("appKind=InfoView&service=%2FInfoViewApp%2Fcommon%2FappService.do"))
                return;

            browser.DocumentCompleted += InboxDocumentCompleted;
        }

        private void Web_V1_NewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
        {
            Processed = true;
            browser.Navigate(URL);
        }

        int documentStep = 0;

        private void InboxDocumentCompleted(object sender, EventArgs e)
        {
            var frame = GetWorkspaceBodyFrame();

            if (frame == null) return;

            var tableReports = frame.Document.GetElementById("ListingURE_listMainTable");

            if (tableReports == null) return;

            var tbody = tableReports.Children.Cast<HtmlElement>().FirstOrDefault(x => x.TagName.ToUpper() == "TBODY");

            if (tbody == null) return;

            documentStep++;
            if (documentStep < 6) return;

            browser.DocumentCompleted -= InboxDocumentCompleted;
            Log(string.Format("Looking for report '{0}'", reportName));

            var report = GetReports(tbody.Children.Cast<HtmlElement>().ToList(), reportName);

            if (report != null)
            {
                var myHidden = tableReports.Document.GetElementById(string.Format("ListingURE_doubleClickAction{0}", report.Index));
                ReportRefreshLoadCompleted(myHidden);
            }
            else
            {
                Log(string.Format("#Error No report was found named '{0}'", reportName));
                Environment.Exit(Environment.ExitCode);
            }


        }

        string lastRefreshData;
        static readonly string JavascriptRefreshDate = string.Format("{0}.frames['webiViewFrame'].document.getElementById('statusRefDate').innerHTML", JavascriptFrameBody);
        private System.Timers.Timer timerParametersWindow = new System.Timers.Timer { Interval = 2000 };

        private void ReportRefreshLoadCompleted(HtmlElement myHidden)
        {
            Log("Opening report");

            var val = myHidden.GetAttribute("value");
            val = val.Substring("javascript:".Length);
            val = val.Replace("cafAction", "invokeAction");

            var frame = GetWorkspaceBodyFrame();
            frame.Document.InvokeScript("eval", new string[] { val });

            browser.DocumentCompleted += OpenReportCompleted;


        }

        void OpenReportCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            browser.DocumentCompleted -= OpenReportCompleted;

            startParametersWindows = DateTime.Now;
            timerParametersWindow.Elapsed += timerParametersWindow_Elapsed;
            timerParametersWindow.Start();

            browser.DocumentCompleted += RefreshDataCompleted;
        }

        int count = 0;
        void RefreshDataCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (count < 9)
            {
                count++;
                return;
            }
            browser.DocumentCompleted -= RefreshDataCompleted;

            //var refreshDateFound = false;

            //while (!refreshDateFound)
            //    refreshDateFound = 
            browser.WaitUntilExist(JavascriptRefreshDate, 2000);

            lastRefreshData = (String)browser.Document.InvokeScript("eval", new[] { JavascriptRefreshDate });
            //DownloadReport();

            timerDownloadFile = new System.Timers.Timer(2000);
            timerDownloadFile.Elapsed += timerDownloadFile_Elapsed;
            timerDownloadFile.Start();
        }

        System.Timers.Timer timerDownloadFile;

        private void timerDownloadFile_Elapsed(object sender, ElapsedEventArgs e)
        {
            BeginInvoke(new timerPointer(DownloadReport));
        }

        private void DownloadReport()
        {
            var currentRefreshData = (String)browser.Document.InvokeScript("eval", new[] { JavascriptRefreshDate });

            Log("Business Objects is refreshing the report");
            if (lastRefreshData == currentRefreshData) return;
            //while (lastRefreshData == currentRefreshData)
            //{
            //    Application.DoEvents();
            //    Thread.Sleep(500);

            //    //if (browser.CanEvalScript)
            //    currentRefreshData = (String)browser.Document.InvokeScript("eval", new[] { JavascriptRefreshDate });
            //}

            timerDownloadFile.Stop();
            Log("Business Objects has been refreshed the report");

            var javascriptLocation = string.Format("{0}.frames['webiViewFrame']", JavascriptFrameBody);
            var javascriptElement = string.Format("{0}.frames['webiViewFrame'].document.getElementById('{1}')", JavascriptFrameBody, "{0}");

            Log("Clicking on 'Document' button");
            browser.WaitUntilExist(string.Format(javascriptElement, "IconImg_Txt_iconMenu_icon_docMenu"));
            ClickOnElement("IconImg_Txt_iconMenu_icon_docMenu", javascriptLocation);

            Log("Clicking on 'Save as in Computer' button");
            browser.WaitUntilExist(string.Format(javascriptElement, "iconMenu_menu_docMenu_span_text_saveDocComputerAs"));
            ClickOnElement("iconMenu_menu_docMenu_span_text_saveDocComputerAs", javascriptLocation);

            Log("Clicking on 'Excel' button");
            browser.WaitUntilExist(string.Format(javascriptElement, "saveDocComputerMenu_span_text_saveXLS"));
            ClickOnElement("saveDocComputerMenu_span_text_saveXLS", javascriptLocation);

            Log("Download will start soon");
            UpdateFormTitle("Download will start soon");

            //browser.Navigating += webBrowser_Navigating;
            //browser.FileDownload += new EventHandler(browser_FileDownload);
            //browser.FileDownload+=new EventHandler(browser_FileDownload);
            axbrowser.DownloadBegin += new SHDocVw.DWebBrowserEvents_DownloadBeginEventHandler(axbrowser_DownloadBegin);
            axbrowser.DownloadComplete += new SHDocVw.DWebBrowserEvents_DownloadCompleteEventHandler(axbrowser_DownloadComplete);
        }

        void axbrowser_DownloadComplete()
        {
            //throw new NotImplementedException();
        }

        void axbrowser_DownloadBegin()
        {
            
        }

        int countStartDownload = 0;
        void browser_FileDownload(object sender,  object e)
        {
            if (countStartDownload == 0)
            {
                countStartDownload++;
                return;
            }

            DownloadBegin();
            //new SHDocVw.WebBrowser().DownloadBegin += new SHDocVw.DWebBrowserEvents2_DownloadBeginEventHandler(BoExtraction_DownloadBegin);
        }

        //[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        //static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);

        //[DllImport("user32.dll", SetLastError = true)]
        //public static extern uint SendInput(uint nInputs, User32.Input[] pInputs, int cbSize);

       

     

        private void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            //e.Cancel = true;
            //var client = new WebClient();

            //client.DownloadDataCompleted += client_DownloadDataCompleted;
            //client.DownloadDataAsync(e.Url);
        }

        void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {
            string filepath = pathToSave;
            File.WriteAllBytes(filepath, e.Result);
            MessageBox.Show("File downloaded");
        }

        private bool ClickOnElement(string elementToClickId, string locationElement, WebBrowserDocumentCompletedEventHandler eventRemove = null, WebBrowserDocumentCompletedEventHandler eventAdd = null)
        {
            var javascriptClick = string.Format("{0}.document.getElementById('{1}')", locationElement, elementToClickId);

            if (!browser.AllElementExist(javascriptClick)) return false;

            if (eventRemove != null)
                browser.DocumentCompleted -= eventRemove;

            if (eventAdd != null)
                browser.DocumentCompleted += eventAdd;

            browser.Document.InvokeScript("eval", new[] { string.Format("{0}.click();", javascriptClick) });
            return true;
        }

        private void UpdateFormTitle(string message)
        {
            Text = string.Format("{0} - {1}", browser.Document.Title, message);
        }

        static void Log(string message)
        {
            File.AppendAllLines(LogPath, new[] { message });
        }

        private Report GetReports(IList<HtmlElement> trs, string reportName)
        {
            var reports = new List<Report>();

            foreach (var tr in trs)
            {
                try
                {
                    reports.Add(new Report
                    {
                        ElementClick = tr.Children[0],
                        //Title = tr.Children[2].Children[0].InnerText
                        Title = tr.Children[6].Children[0].GetElementsByTagName("a")[0].GetAttribute("title"),
                        Index = tr.Children[0].FirstChild.Id.Replace("ListingURE_listColumn_", string.Empty).Replace("_0_0", string.Empty)
                    });
                }
                catch { }
            }

            return reports.FirstOrDefault(x => x.Title == reportName);
        }

        private HtmlWindow GetWorkspaceBodyFrame()
        {
            var frame = browser.Document.Window.Frames["headerPlusFrame"];

            frame = frame.Frames.Cast<HtmlWindow>().FirstOrDefault(x => x.Name == "dataFrame");
            if (frame == null) return null;

            frame = frame.Frames.Cast<HtmlWindow>().FirstOrDefault(x => x.Name == "workspaceFrame");
            if (frame == null) return null;

            return frame.Frames.Cast<HtmlWindow>().FirstOrDefault(x => x.Name == "workspaceBodyFrame");
        }

        #region When parameters windows shows

        static DateTime startParametersWindows;

        public delegate void timerPointer();

        private void timerParametersWindow_Elapsed(object sender, ElapsedEventArgs e)
        {
            BeginInvoke(new timerPointer(ClickOkParametersWindow));
        }

        private void ClickOkParametersWindow()
        {
            var buttonId = "theBttnCenterImgpromptsOKButton";
            var location = string.Format("{0}.{1}", JavascriptFrameBody, "frames['webiViewFrame']");
            var javascriptButtonRunQuery = string.Format("{0}.document.getElementById('{1}')", location, buttonId);
            var found = false;

            try
            {
                found = browser.AllElementExist(javascriptButtonRunQuery);
            }
            catch { }

            if (!found && (startParametersWindows - DateTime.Now).TotalSeconds <= 60) return;

            timerParametersWindow.Stop();
            ClickOnElement(buttonId, location, null, null);
        }

        #endregion

        
        void DownloadBegin()
        {
            uint processId = 0;
            WindowsAPI.GetWindowThreadProcessId((IntPtr)0x00000000006C213C, out processId);

            while (processId == 0)
            {
                Application.DoEvents();
                Thread.Sleep(100);
            }

           WindowsAPI.PostMessage((IntPtr)0x00000000006C213C, WindowsAPI.WM_CHAR, WindowsAPI.VK_RETURN, 0);
            
            //SendMessage(0x00000000006C213C, WM_CHAR, (IntPtr)0x0D, IntPtr.Zero);
            //SendMessage(0x00000000006C213C, );
        }

    }

    

 public class WindowsAPI
     {
         ///<summary>
         ///
         ///</ Summary>
         public const uint WM_KEYDOWN = 0x100;

         ///<summary>
         ///
         ///</ Summary>
         public const uint WM_KEYUP = 0x101;

         ///<summary>
         ///
         ///</ Summary>
         public const uint WM_LBUTTONDOWN = 0x201;

         ///<summary>
         ///
         ///</ Summary>
         public const uint WM_LBUTTONUP = 0x202;

         public const uint WM_CHAR = 0x102;

         ///<summary>
         ///
         ///</ Summary>
         public const int MK_LBUTTON = 0x01;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_RETURN = 0x0d;

         public const int VK_ESCAPE = 0x1b;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_TAB = 0x09;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_LEFT = 0x25;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_UP = 0x26;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_RIGHT = 0x27;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_DOWN = 0x28;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_F5 = 0x74;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_F6 = 0x75;

         ///<summary>
         ///
         ///</ Summary>
         public const int VK_F7 = 0x76;

         ///<summary>
         ///The function returns a GetForegroundWindow handle to the foreground window.
         ///</ Summary>
         [DllImport ("user32.dll")]
         public static extern IntPtr GetForegroundWindow ();

         [DllImport ("kernel32.dll")]
         public static extern uint GetCurrentThreadId ();

         [DllImport ("user32.dll", SetLastError = true)]
         public static extern uint GetWindowThreadProcessId (IntPtr hWnd, out uint lpdwProcessId);

         [DllImport ("user32.dll")]
         public static extern bool AttachThreadInput (uint idAttach , uint idAttachTo, bool fAttach );

         [DllImport ("kernel32.dll", SetLastError = true)]
         public static extern bool ReadProcessMemory (
           IntPtr hProcess,
           IntPtr lpBaseAddress,
           [Out ()] byte [] lpBuffer,
           int dwSize,
           int lpNumberOfBytesRead
          );
                
         public static void SwitchWindow (IntPtr windowhandle)
         {
             if (GetForegroundWindow() == windowhandle)
                 return;

             IntPtr foregroundWindowHandle = GetForegroundWindow();
             uint currentThreadId  = GetCurrentThreadId ();
             uint temp;
             uint foregroundThreadId =  GetWindowThreadProcessId (foregroundWindowHandle, out temp);
             AttachThreadInput (currentThreadId, foregroundThreadId, true);
             SetForegroundWindow (windowhandle);
             AttachThreadInput (currentThreadId, foregroundThreadId, false);

             while (GetForegroundWindow () != windowhandle)
             {
             }
         }

         ///<summary>
         ///
         ///</ Summary>
         ///<param Name="hwndParent"> </ param>
         ///<param Name="hwndChildAfter"> </ param>
         ///<param Name="lpszClass"> </ param>
         ///<param Name="lpszWindow"> </ param>
         ///<returns> </ Returns>
         [DllImport ("user32.dll", SetLastError = true)]
         public static extern IntPtr FindWindowEx (IntPtr hwndParent, IntPtr hwndChildAfter,  string lpszClass, string lpszWindow);

         ///<summary>
         ///
         ///</ Summary>
         ///<param Name="hWnd"> </ param>
         ///<param Name="msg"> </ param>
         ///<param Name="wParam"> </ param>
         ///<param Name="lParam"> </ param>
         ///<returns> </ Returns>
         [DllImport ("user32.dll", EntryPoint = "PostMessageA")]
         public static extern bool PostMessage (IntPtr hWnd, uint msg, int wParam, int lParam);

         ///<summary>
         ///
         ///</ Summary>
         ///<param Name="ch"> </ param>
         ///<returns> </ Returns>
         [DllImport ("user32.dll")]
         public static extern byte VkKeyScan (char ch);

         [DllImport ("user32.dll")]
         public static extern uint MapVirtualKey ( uint uCode, uint uMapType);

         ///<summary>
         ///
         ///</ Summary>
         ///<param Name="name"> </ param>
         ///<returns> </ Returns>
         public static IntPtr FindWindow (string name)
         {
             Process [] procs = Process.GetProcesses ();

             foreach (Process proc in procs)
             {
                 if (name == proc.MainWindowTitle)
                 {
                     return proc.MainWindowHandle ;
                 }
             }

             return IntPtr.Zero;
         }

         [DllImport ("user32.dll")]
         public static extern IntPtr SetFocus (IntPtr hWnd);

         [DllImport ("user32.dll")]
         [Return: MarshalAs (UnmanagedType.Bool)]
         public static extern bool SetForegroundWindow (IntPtr hWnd);

         ///<summary>
         ///
         ///</ Summary>
         ///<param Name="low"> </ param>
         ///<param Name="high"> </ param>
         ///<returns> </ Returns>
         public static int MAKELONG (int low, int high)
         {
             return (high << 16) | (low & 0xffff);
         }
    
         [DllImport ("User32.dll")]
         public static extern uint SendInput (uint numberOfInputs, [MarshalAs (UnmanagedType.LPArray, SizeConst = 1)] INPUT [] input, int structSize); 

         [DllImport ("user32.dll")]
         public static extern IntPtr GetMessageExtraInfo ();

         public const int INPUT_MOUSE = 0;
         public const int INPUT_KEYBOARD = 1;
         public const int INPUT_HARDWARE = ​​2;
         public const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
         public const uint KEYEVENTF_KEYUP = 0x0002;
         public const uint KEYEVENTF_UNICODE = 0x0004;
         public const uint KEYEVENTF_SCANCODE = 0x0008;
         public const uint XButton1 = 0x0001;
         public const uint XButton2 = 0x0002;
         public const uint MOUSEEVENTF_MOVE = 0x0001;
         public const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
         public const uint MOUSEEVENTF_LEFTUP = 0x0004;
         public const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
         public const uint MOUSEEVENTF_RIGHTUP = 0x0010;
         public const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020;
         public const uint MOUSEEVENTF_MIDDLEUP = 0x0040;
         public const uint MOUSEEVENTF_XDOWN = 0x0080;
         public const uint MOUSEEVENTF_XUP = 0x0100;
         public const uint MOUSEEVENTF_WHEEL = 0x0800;
         public const uint MOUSEEVENTF_VIRTUALDESK = 0x4000;
         public const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
     }

     [StructLayout (LayoutKind.Sequential)]
     public struct MOUSEINPUT
     {
         int dx;
         int dy;
          uint mouseData;
         uint dwFlags;
         uint team;
         IntPtr dwExtraInfo;
     }

     [StructLayout (LayoutKind.Sequential)]
     public struct KEYBDINPUT
     {
         public ushort wVk;
         public ushort WSCAN;
         public uint dwFlags;
         public uint team;
         public IntPtr dwExtraInfo;
     }

     [StructLayout (LayoutKind.Sequential)]
     public struct HARDWAREINPUT
     {
         uint uMsg;
         ushort wParamL;
         ushort wParamH;
     }

     [StructLayout (LayoutKind.Explicit)]
     public struct INPUT
     {
         [FieldOffset (0)]
         public int type;
         [FieldOffset (4)] 
         public MOUSEINPUT mi;
         [FieldOffset (4)] 
         public KEYBDINPUT ki;
         [FieldOffset (4)] 
         public HARDWAREINPUT hi;
     } 
}
